<!doctype html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>喷发物分析仪-挥发分分析仪</title>
  <link rel="stylesheet" href="/static/css/bootstrap.min.css">
  <link rel="stylesheet" href="/omsp/qv.css">
  <link rel="stylesheet" href="/omsp/qv-table.css">
  <script src="/static/js/jquery-3.6.0.min.js"></script>
  <script src="/static/js/echarts.5.5.js"></script>
  <script src="/static/js/echarts-gl.min.js"></script>
  <script src="/static/js/xtool.js?12"></script>
  <script src="/omsp/qv.js"></script>
  <style>
    .FF {
      height: 20%;
      position: relative;
    }

    .FF + .FF {
      border-top: 1px solid #ccc
    }

    .FF .chart {
      display: inline-block;
      height: 100%;
      width: calc(100% - 550px);
    }

    .FF .infow {
      display: inline-block;
      height: 100%;
      width: 539px;
      font-size: 12px;
    }
    .table-sm>:not(caption)>*>* {
        padding: 1px .25rem;
    }
    td > kbd {
      font-size: 12px;
    }
  </style>
</head>
<body class="M1">
<div id="CCC" style="padding: 4px 6px;display: flex;flex-direction: row">
  <button class="btn btn-primary btn-sm disactive-btn" onclick="main.realtime()" id="realtime">实时</button>
  <button class="btn btn-primary btn-sm mx-1" id="history" onclick="main.history()">历史</button>
  日期:
  <input id="day" type="date" value="">
  任务:
  <select id="task" class="sele-comp"></select>
  方法:
  <select id="fangfa" class="sele-comp" onchange="main.set_ff(this.value);">
    <option value="0">不限</option>
    <option value="1">方法 1</option>
    <option value="2">方法 2</option>
    <option value="3">方法 3</option>
    <option value="4">方法 4</option>
    <option value="5">方法 5</option>
  </select>
  最大帧: <label id="frm_max"></label>
  数据帧:<input id="frm_input" oninput="this.nextElementSibling.value=this.value" style="min-width: 60px">
  <input oninput="this.previousElementSibling.value=this.value" style="padding:0;flex-grow: 2"
         id="frm_range" type="range" min="0" max="0" value="0" step="1">
  <button class="btn btn-primary btn-sm history"  onclick="main.exportCSV(this)"><i class="fa fa-file-text"></i>下载帧信息</button>

</div>
<div class="d-flex d-flex flex-row" style="height: calc(100vh - 43px)">
  <div class="flex-grow-1">
    <div class="FF"></div>
    <div class="FF"></div>
    <div class="FF"></div>
    <div class="FF"></div>
    <div class="FF"></div>
  </div>
</div>
</body>
<script>
  let vita_param = [
    {n: "时间码", k: "time", v: BJT},
    {n: "计数值总个数", k: "n_cnt", r: '4X'},
    {n: "同步头", k: "syn", v: new RawFmt('4X').X, r: '4X'},
    {n: "帧计数", k: "cnt", r: '4X'},
    {n: "测量方法", k: "type_m", r: '4b'},
    {
      n: "频率", k: "tf", v: (v) => {
        return (v & 0xF) ? '高' : '低'
      }, r: {fmt:(v) => {
        return '0b'+(v & 0xF).toString(2).padStart(4, 0)
      }}
    },
    {n: "灯丝", k: "ds", r: '4X'},
    {n: "灯丝电流", k: "I", v: XFMT_Fixed(), r: '4X'},
    {n: "射频温度", k: "T", v: XFMT_Fixed(), r: '4X'},
    {n: "倍增器电压", k: "U",r:'4X'},
    {n: "射频幅值监测点1", k: "A_1",v: XFMT_Fixed(), r: '4X'},
    {n: "射频幅值监测点2", k: "A_2",v: XFMT_Fixed(), r: '4X'},
    {n: "射频幅值监测点3", k: "A_3",v: XFMT_Fixed(), r: '4X'},
    {n: "射频幅值监测点4", k: "A_4",v: XFMT_Fixed(), r: '4X'},
    {n:"探测器姿态Q0",k:"Q0",v: XFMT_Fixed(),r:'2X'},
    {n:"发动机状态_高压灯丝使能状态",k:"hfs",r:'4b'},
    {n:"发动机状态_指令",k:"da",r:'4b'},
  ]
  class FF {
    constructor(ob, n) {
      this.n = n
      this.$o = ob;
      ob.innerHTML = `
<div class="chart"></div>
<div class="infow">
<table class="table table-hover table-bordered table-sm small mt-2 mb-0"><tbody class="info"></tbody></table>
</div>`
      this.$c = echarts.init(ob.querySelector('.chart'))
      this.$i = ob.querySelector('.info')
      this.$c.setOption(this.defOption)

      this.resize = this.$c.resize
      this.setOption = this.$c.setOption
    }

    get defOption() {
      return {
        title: {text: `方法${this.n + 1}`, textStyle: {fontSize: 16, fontWeight: 700}},
        grid: {top: 25, left: 80, right: 30, bottom: 25},
        xAxis: {type: 'value'},
        yAxis: {type: 'value'},
        series: {type: 'line'}
      }
    }

    render_frame(d, data, index) {
      let v = d.info;
      let f = v.tf >> 4
      let t = v.tf & 0xF
      let tobin4 = new RawFmt('4b')
      this.$i.innerHTML = `
      <tr><th>时间码</th><td title="${v.time_}">${BJT(v.time)}</td>
           <th>计数值总个数</th><td>${v.n_cnt} <kbd>0x${fmtHEX(v.n_cnt, 4)}</kbd></td></tr>
      <tr><th>同步头</th><td>${fmtHEX(v.syn, 4)}<kbd>0x${fmtHEX(v.syn, 4)}</kbd></td>
           <th>帧计数</th><td>${v.cnt} <kbd>0x${fmtHEX(v.cnt, 4)}</kbd></td></tr>
      <tr><th>测量方法</th><td>${v.type_m} <kbd>0b${f.toString(2).padStart(4, 0)}</kbd></td>
      <th>频率</th><td>${t ? '高' : '低'}  <kbd>0b${t.toString(2).padStart(4, 0)}</td></tr>
      <tr><th >灯丝</th><td>${v.ds} <kbd>0x${fmtHEX(v.ds_, 4)}</kbd></td>
      <th >灯丝电流</th><td>${fmt(v.I)} A <kbd>0x${fmtHEX(v.I_, 4)}</kbd></td></tr>
      <tr><th>射频温度</th><td>${fmt(v.T)} ℃<kbd>0x${fmtHEX(v.T_, 4)}</kbd></td>
      <th>倍增器电压</th><td>${fmt(v.U)} V<kbd>0x${fmtHEX(v.U_, 4)}</kbd></td></tr>
      <tr><th >射频幅值</th><td colspan="3">${fmt(v.A_1)}, ${fmt(v.A_2)}, ${fmt(v.A_3)}, ${fmt(v.A_4)}
      <kbd>0x${fmtHEX(v.A_4_, 4)}</kbd>
      <kbd>0x${fmtHEX(v.A_3_, 4)}</kbd>
      <kbd>0x${fmtHEX(v.A_2_, 4)}</kbd>
      <kbd>0x${fmtHEX(v.A_1_, 4)}</kbd>
      </td></tr>
      <tr>
      <th>姿态Q0</th><td>${FMT_Fixed(v.Q0)}<kbd>0x${fmtHEX(v.Q0_,2)}</kbd></td>
      <th>高压使能,总线指令</th><td>${v.hfs}, ${tobin4.b(v.da)} <kbd>${tobin4.b(v.da_)}</kbd><kbd>${tobin4.b(v.hfs_)}</kbd> </td>
      </tr>
    `
      this.$c.clear()
      this.$c.setOption({
        title: {text: `方法${this.n + 1}`, subtext: index, textStyle: {fontSize: 16, fontWeight: 700}},
        grid: {top: 25, left: 80, right: 30, bottom: 25},
        xAxis: {type: 'value'},
        yAxis: {type: 'value'},
        series: {type: 'line', data: Array.from(data).map((v, i) => [i, v])}
      })

    }

    reset() {
      this.$c.clear()
      this.$c.setOption(this.defOption)
    }
  }

  fmt = (v, n) => v ? v.toFixed(n || 3) : v
  const XMode = {
    1: '方法 1',
    2: '方法 2',
    3: '方法 3',
    4: '方法 4',
    5: '方法 5'
  }
  st_frames = (frames) => {
    // 0: '不限',
    let r = {}
    let selected = $('#fangfa').val()
    frames.forEach(v => r[v.mode] = (r[v.mode] || 0) + 1)
    let fr = Object.keys(XMode).map(k => `<option value='${k}' >${XMode[k]}/${r[k] || 0} </option> `).join('')
    $('#fangfa').html('<option value="0">不限</option>' + fr)
    $('#fangfa').val(selected)
  }

  class Page extends Realtime {
    constructor() {
      super('ADVA-VITA', $STATION, vita_param)
      this.c = Array.from($$$('.FF')).map((o, i) => new FF(o, i))
      this.cf = {}
      // window.onresize = () => charts.forEach(v => v.resize());
      this.$ff = $$('#fangfa')
      this.$frm_max = $$('#frm_max')
      this.frames = []
      this.$frmr.onchange = this.select_frame.bind(this)
      this.ff = 0;
      window.onresize = this.resize.bind(this)
    }
    resize(){
      this.c.forEach(v=>v.$c.resize())
    }

    async onTask() {
      await super.onTask();
      st_frames(this.frames_ori)
      this.filter_frames(parseInt(this.$ff.value))
      this.seek(this.$frmr.value, false)
    }

    async load_task() {
      let t = await super.load_task();
      st_frames(this.frames_ori)
      return t
    }

    select_frame(ev) {
      let curid = this.$frmi.value = this.$frmr.value = ev.target.value;
      this.seek(parseInt(curid), true)
    }

    reset() {
      super.reset()
      $('.info').html('')
      this.c.forEach(ec => ec.reset())
      // this.c.forEach(ec => ec.$c.setOption({series: {data: []}}))
    }

    async newframe(d) {
      super.newframe(d);
      if ((!this.ff || this.ff === d.mode)) {
        this.frames.push(d);
        this.$frm_max.innerText = this.$frmr.max = this.frames.length - 1
        this.showframe(d);
      }
    }

    params(v) {
      let i = v.info;
      console.log("@params", v, 'call showframe()')
      this.showframe(v)
      // this.$info.innerHTML = this._params.map(c => c.view_tr(i)).join('')
    }

    set_ff(ffid) {

      ffid = this.ff = parseInt(ffid)
      if (ffid) {
        this.close()
        this.frames = this.frames_ori.filter(v => v.mode === ffid)
        if (!this.frames.length) {
          alert(`没有方法 ${ffid} 的数据`)
          this.frames = this.frames_ori;
          ffid = 0
        }
      } else this.frames = this.frames_ori;
      st_frames(this.frames_ori)
      this.$ff.value = ffid || 0;
      this.c.forEach((v, i) => {
        v.$o.style.backgroundColor = (ffid && ffid === i + 1) ? '#CEF' : 'unset';
      })
      this.resetFrmInput();
      this.frame_index = this.$frmr.max
      this.seek(this.$frmr.max)
    }

    async showframe(d) {
      let f = d.frm;
      let bufr = await $api(`omsp.bindata?t=${this.cur_task}&offset=${f[0]}&size=${f[1]}`, null, v => v.arrayBuffer());
      return this.c[d.mode - 1].render_frame(d, new Int16Array(bufr), this.frames.indexOf(d))
    }

    async newtask(d) {
      let t = await super.newtask(d);
      this.cf = {}
      this.frames_ori.forEach(v => this.cf[v.mode] = v);
      this.set_ff(0)
      this.frames = this.frames_ori;
      Object.values(this.cf).forEach(v => this.showframe(v))
      this.$ff.selectedIndex = 0;
      return t;
    }

    seek(n, singleFrame) {
      n = parseInt(n)
      super.seek(n)
      if (singleFrame) {
        let frame = this.frames[n]
        if (frame) {
          this.showframe(frame)
        }
      } else {
        let cf = {}, i, v
        for (i = 0; i < n; i++) {
          v = this.frames[i];
          cf[v.mode] = v
        }
        Object.values(cf).forEach(v => {
          if (v !== this.cf[v.mode]) this.showframe(v)
        })
      }

    }
  }

  main = new Page()
  main.realtime()
</script>
</html>